from Distance import *
from InitPop import *
from DrawPath import *
from OutputPath import *
from Fitness import *
from Select import *
from Recombin import *
from Mutate import *
from Reverse import *
from mySort import *
from Reins import *
from loadFile import *


def getData():  # 从文件或直接输入
    X = readFromExcelByPandas(r'citys.xls')
    return X


def saveData(NIND, MAXGEN, Pc, Pm, bestVale):   # 记录每次数据
    with open(r'record.csv', 'a') as f:
        lst = [NIND, MAXGEN, Pc, Pm, bestVale]
        item = [str(i) for i in lst]
        f.write(','.join(item) + "\n")
        f.close()


if __name__ == '__main__':
    # 获取城市的位置坐标
    X = getData()
    X = np.array(X)
    NIND = 30  # 种群大小
    MAXGEN = 3000  # 迭代最大代数
    Pc = 0.79     # 交叉概率
    Pm = 0.1903  # 变异概率
    D = Distance(X)  # 生成距离矩阵
    N = D.shape[1]
    #  初始化种群
    Chrom = InitPop(NIND, N)
    # 画出随机解的路线图
    DrawPath(Chrom[0, ], X)
    # 输出随机解的路线和总距离
    print('初始种群中的一个随机值:')
    OutputPath(Chrom[0, ])
    print('总距离为%f' % PathLength(D, Chrom[0, ]))
    print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
    # 优化过程
    gen = 0  # 代数
    figure('完整的优化过程')
    xlim(0, MAXGEN)
    title('优化过程')
    xlabel('代数')
    ylabel('当前最优值')
    ObjV = PathLength(D, Chrom)
    preObjV = np.min(ObjV)  # 当前种群种最优值
    while gen < MAXGEN:
        # 计算适应度
        ObjV = PathLength(D, Chrom)
        plot([gen - 1, gen], [preObjV, np.min(ObjV)])
        preObjV = np.min(ObjV)
        FitnV = Fitness(ObjV)
        [_, sbuf] = mySort(FitnV)  # 根据适应度排序
        # 选择
        Selch = Select(Chrom, FitnV)
        # 交叉操作
        Selch = Recombin(Selch, Pc)
        # 变异
        Selch = Mutate(Selch, Pm)
        # 逆转操作
        Selch = Reverse(Selch, D)
        # 重新插入子代的新种群中
        Chrom = Reins(Chrom, Selch, sbuf)
        # 更新
        gen = gen + 1
        # gen = MAXGEN
    # 画出最优解的路线和总距离
    ObjV = PathLength(D, Chrom)
    [nums, idx] = mySort(ObjV)
    chrom = Chrom[idx[0],]
    DrawPath(chrom, X)
    # 输出最优解的路线和总距离
    print('最优解')
    OutputPath(chrom)
    print('总距离为%f' % ObjV[idx[0]])
    saveData(NIND, MAXGEN, Pc, Pm, ObjV[idx[0]][0])
    print('----------------------------------------------------------------')
    show()
